// sm2_sign.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "utils.h"

int main(int argc, char *argv[]) {
    if (argc < 4 || argc > 5) {
        fprintf(stderr, "Usage: %s <input_file> <privkey.pem> <sig_file> [id]\n", argv[0]);
        exit(1);
    }

    const char *in_file = argv[1];
    const char *privkey_file = argv[2];
    const char *sig_file = argv[3];
    const char *id = (argc == 5) ? argv[4] : "1234567812345678";

    size_t in_len;
    unsigned char *in_data = read_file(in_file, &in_len);

    FILE *fp = fopen(privkey_file, "r");
    EVP_PKEY *pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
    fclose(fp);
    if (!pkey) {
        fprintf(stderr, "Failed to read private key\n");
        exit(1);
    }

    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
    if (!md_ctx) goto err;

    if (EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) <= 0 ||
        EVP_PKEY_CTX_set_ec_scheme(EVP_MD_CTX_pkey_ctx(md_ctx), NID_sm2) <= 0 ||
        EVP_PKEY_CTX_set1_id(EVP_MD_CTX_pkey_ctx(md_ctx), id, strlen(id)) <= 0) goto err;

    size_t sig_len;
    if (EVP_DigestSign(md_ctx, NULL, &sig_len, in_data, in_len) <= 0) goto err;

    unsigned char *sig = malloc(sig_len);
    if (!sig) goto err;

    if (EVP_DigestSign(md_ctx, sig, &sig_len, in_data, in_len) <= 0) {
        free(sig);
        goto err;
    }

    write_file(sig_file, sig, sig_len);
    free(sig);
    EVP_MD_CTX_free(md_ctx);
    EVP_PKEY_free(pkey);
    free(in_data);
    printf("SM2 signature created.\n");
    return 0;

err:
    fprintf(stderr, "SM2 signing failed.\n");
    EVP_MD_CTX_free(md_ctx);
    EVP_PKEY_free(pkey);
    free(in_data);
    exit(1);
}
